import copy
import random

from Location import Location
from Location import Direction


class GameCoreController:

    def __init__(self):
        self.__map = [
            [0] * 4,
            [0] * 4,
            [0] * 4,
            [0] * 4
        ]
        # self.__map = [
        #     [2, 4, 2, 4],
        #     [8, 16, 4, 32],
        #     [32, 4, 2, 64],
        #     [64, 32, 16, 0]
        # ]
        # 用于存储去零合并的列表
        self.__list_merge = []
        # 用途存储空位置的列表
        self.__list_empty_location = []
        # 地图是否发生变化
        self.is_change = False

    @property
    def map(self):
        return self.__map

    @property
    def is_change(self):
        return self.__is_change

    @is_change.setter
    def is_change(self, value):
        self.__is_change = value

    def __move_zero_end(self):
        """
            将0移动到末尾
        :return:
        """
        for i in range(len(self.__list_merge) - 1, -1, -1):
            if self.__list_merge[i] == 0:
                del self.__list_merge[i]
                self.__list_merge.append(0)
        return self.__list_merge

    def __merge(self):
        """
            合并相邻且一样的数
        :return:
        """
        self.__move_zero_end()
        for i in range(len(self.__list_merge) - 1):
            if self.__list_merge[i] == self.__list_merge[i + 1]:
                self.__list_merge[i] += self.__list_merge[i + 1]
                self.__list_merge[i + 1] = 0
        self.__move_zero_end()

    def __move_left(self):
        """
            将二维数组的行合并数向左移动
        :return:
        """
        for arr in self.__map:
            self.__list_merge[:] = arr
            self.__merge()
            arr[:] = self.__list_merge
        return self.__map

    def __move_right(self):
        """
                    将二维数组的行合并数向右移动
                :return:
                """
        for arr in self.__map:
            self.__list_merge[:] = arr[::-1]
            self.__merge()
            arr[:] = self.__list_merge[::-1]

        return self.__map

    def __move_top(self):
        """
            将二维数组的行合并数向上移动
        :return:
        """

        for col in range(len(self.__map[0])):
            self.__list_merge.clear()
            for row in range(len(self.__map)):
                self.__list_merge.append(self.__map[row][col])
            self.__merge()
            for row in range(len(self.__map)):
                self.__map[row][col] = self.__list_merge[row]
        return self.__map

    def __move_end(self):
        """
            将二维数组的行合并数向下移动
        :return:
        """

        for col in range(len(self.__map[0])):
            self.__list_merge.clear()
            for row in range(len(self.__map)):
                self.__list_merge.append(self.__map[row][col])
            self.__list_merge = self.__list_merge[::-1]
            self.__merge()
            self.__list_merge = self.__list_merge[::-1]
            for row in range(len(self.__map)):
                self.__map[row][col] = self.__list_merge[row]
        return self.__map

    def move(self, dir):
        self.__is_change = False
        # 移动前记录地图
        original_map = copy.deepcopy(self.__map)
        if dir == Direction.up:
            self.__move_top()
        elif dir == Direction.down:
            self.__move_end()
        elif dir == Direction.left:
            self.__move_left()
        elif dir == Direction.right:
            self.__move_right()
        # 移动后地图是否变化
        self.is_change = self.__equal_map(original_map)

    def __equal_map(self, original):
        """

        :param original:
        :return:
        """
        for r in range(4):
            for c in range(4):
                if original[r][c] != self.__map[r][c]:
                    return True
        return False

    def __calculate_empty_location(self):
        """
            获取为空的位置
        :return:
        """
        self.__list_empty_location.clear()
        for r in range(4):
            for c in range(4):
                if self.__map[r][c] == 0:
                    loc = Location(r, c)
                    self.__list_empty_location.append(loc)

    def generate_new_number(self):
        """
            随机生成一个数
        :return:
        """
        self.__calculate_empty_location()
        if len(self.__list_empty_location) == 0:
            return 0
        # 从空位置列表中，随机选择一个元素
        loc = random.choice(self.__list_empty_location)
        self.__map[loc.r_index][loc.c_index] = 4 if random.randint(1, 10) == 1 else 2
        self.__list_empty_location.remove(loc)

    def is_game_over(self):
        """
            游戏是否结束
        :return:
        """
        if len(self.__list_empty_location) > 0:
            return False
        # 横向具有相同元素  游戏不能结束
        # for r in range(4):
        #     for c in range(3):
        #         if self.__map[r][c] == self.__map[r][c + 1]:
        #             return False
        # # 竖向具有相同元素 游戏不能结束
        # for c in range(4):
        #     for r in range(3):
        #         if self.__map[r][c] == self.__map[r + 1][c]:
        #             return False
        # 横向、纵向同时比对
        for r in range(4):
            for c in range(3):
                if self.__map[r][c] == self.__map[r][c + 1] or self.__map[c][r] == self.__map[c + 1][r]:
                    return False

        return True

    def output(self):
        """
            将二维数组输出到控制台
        :return:
        """
        for arr in self.__map:
            print(" ".join([str(i) for i in arr]))
        print("---------------------")


if __name__ == "__main__":
    gc = GameCoreController()
    gc.output()
    # gc.move_top()
    # gc.output()
    # gc.move_end()
    # gc.output()
    # gc.move_left()
    # gc.output()
    # gc.move_right()
    # gc.output()

    gc.generate_new_number()
    gc.generate_new_number()
    gc.generate_new_number()
    gc.generate_new_number()
    gc.generate_new_number()
    gc.generate_new_number()
    gc.generate_new_number()
    gc.generate_new_number()
    gc.output()
